﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Events;
using VisualStock.Infrastructure;
using VisualStock.Infrastructure.Interfaces;
using VisualStock.Infrastructure.Models;
using VisualStock.Modules.StockMarket.HistoricalData.Interfaces;
using VisualStock.Modules.StockMarket.Services;

namespace VisualStock.Modules.StockMarket.HistoricalData
{
    public class HistoricalDataChartViewModel : IHistoricalDataChartViewModel, INotifyPropertyChanged
    {
        #region Private Field

        private readonly IHistoricalDataService historicalDataService;

        // Defines the historical data which are being displayed in the chart. 
        private List<StockHistoricalDataCollection> _currentDataCollections = new List<StockHistoricalDataCollection>();

        private List<StockHistoricalDataCollection> _originalDatacollections = new List<StockHistoricalDataCollection>();

        // Defines the the symbols which are being displayed in the chart;
        private ObservableCollection<string> _currentSymbolList = new ObservableCollection<string>();

        #endregion

        public HistoricalDataChartViewModel(IHistoricalDataChartView view, IHistoricalDataService historicalDataService, IEventAggregator eventAggregator, ISettingController observableSettings)
        {
            this.historicalDataService = historicalDataService;
            this.Settings = observableSettings;
            this.Settings.PropertyChanged += new PropertyChangedEventHandler(OnSettingsChanged);
            this.View = view;
            this.View.Model = this;
            eventAggregator.GetEvent<NewComparisonRequestedEvent>().Subscribe(ResetCurrentSymbolList, ThreadOption.UIThread);
        }

        /// <summary>
        /// Reset the current symbol list
        /// </summary>
        /// <param name="newSymbolList"></param>
        public void ResetCurrentSymbolList(List<string> newSymbolList)
        {
            if (newSymbolList == null || newSymbolList.Count == 0) return;

            // Reset the _currentSymbolList
            _currentSymbolList.Clear();

            for (int i = 0; i < newSymbolList.Count; i++)
            {
                _currentSymbolList.Add(newSymbolList[i]);
            }

            this.UpdateDataCollection();
        }

        private void UpdateDataCollection()
        {
            // Return if the CurrentStartDate and CurrentEndDate have not been initialized
            if (Settings.CurrentStartDate.Ticks == 0 || Settings.CurrentEndDate.Ticks == 0) return;

            // Clear all the old items in _currentDataSeriesCollection
            _currentDataCollections.Clear();

            // Add the new data collections of the new symbols into _currentDataCollection
            for (int i = 0; i < _currentSymbolList.Count; i++)
            {
                _currentDataCollections.Add(this.historicalDataService.GetHisroricalData(_currentSymbolList[i], Settings.CurrentStartDate, Settings.CurrentEndDate));
            }

            ResetRelativeXValue();
            ResetRelatvieYValue();
            this.InvokePropertyChanged("CurrentDataCollections");

            _originalDatacollections = _currentDataCollections;
        }

        private void ResetRelatvieYValue()
        {
            if (_currentDataCollections.Count > 1 && !_currentSymbolList[1].Contains(_currentSymbolList[0] + "_"))
            {
                foreach (StockHistoricalDataCollection collection in _currentDataCollections)
                {
                    collection[collection.Count-1].RelativeYValue = 0;
                    for (int i = 0; i < collection.Count - 1 ; i++)
                    {
                        // Since the collection is in newest first order
                        collection[i].RelativeYValue = (collection[i].ClosingPrice - collection[i + 1].ClosingPrice) / collection[i + 1].ClosingPrice;
                    }
                }
            }
            else
            {
                foreach (StockHistoricalDataCollection collection in _currentDataCollections)
                {
                    for (int i = 0; i < collection.Count; i++)
                    {
                        collection[i].RelativeYValue = collection[i].ClosingPrice;
                    }
                }
            }
        }

        private void ResetRelativeXValue()
        {
            // Set up the DateTime to RelativeXValue corresponding table
            Dictionary<DateTime, int> cTable =
                DataAnalysisService.RelativeXValueCalculation(Settings.CurrentStartDate, Settings.CurrentEndDate);

            // Set the RelativeXValue for each data collection
            foreach (StockHistoricalDataCollection dataCollection in _currentDataCollections)
            {
                foreach (StockHistoricalDataItem dataItem in dataCollection)
                {
                    // Look for the corresponding RelativeXValue in the table
                    dataItem.RelativeXValue = cTable[dataItem.QuoteDate];
                }
            }
        }

        private void ReCalculateLogData()
        {
        }

        #region IHistoricalDataChartViewModel Members

        public IHistoricalDataChartView View { get; set; }

        public List<StockHistoricalDataCollection> CurrentDataCollections
        {
            get { return _currentDataCollections; }
            set
            {
                _currentDataCollections = value;
                this.InvokePropertyChanged("CurrentDataCollections");
            }
        }

        public ObservableCollection<string> CurrentSymbolList
        {
            get { return _currentSymbolList; }
        }

        public ISettingController Settings { get; private set; }

        #endregion

        public event PropertyChangedEventHandler PropertyChanged;

        private void InvokePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler Handler = PropertyChanged;
            if (Handler != null) Handler(this, new PropertyChangedEventArgs(propertyName));
        }

        private void OnSettingsChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "CurrentStartDate": UpdateDataCollection(); break;
                case "CurrentEndDate": UpdateDataCollection(); break;
            }
        }
    }
}
